package algo.math.evaluator.stack;
import java.util.Iterator;

import algo.math.evaluator.stack.interfaces.ILifo;
import algo.math.evaluator.stack.interfaces.ILinkSimple;


/**
 * Implementation of a simple linked stack.
 *
 * @param <V> the value type
 */
public class LinkedStackSimple <V> implements ILifo<V>  {

	/** The _head. */
	private ILinkSimple<V> _head;
	
	/** The size. */
	private int size=0;
	
	/**
	 * Instantiates a new linked stack simple.
	 */
	public LinkedStackSimple()
	{
	}
	
	/* (non-Javadoc)
	 * @see algo.math.evaluator.stack.interfaces.ILifo#iterator()
	 */
	@Override
	public Iterator<V> iterator() {
		 
		return new Iterator<V>() {

			 ILinkSimple<V>  beforeNode = null;
			 ILinkSimple<V> currentNode = _head;
			 
			@Override
			public boolean hasNext() {
				
				if (null!=currentNode.getNext())
				{
					return true;
				}
				return false;
			}

			@Override
			public V next() {
				if (hasNext())
				{
					beforeNode = currentNode;
					currentNode = currentNode.getNext();
					return currentNode.getValue();
				}
				return null;
			}

			@Override
			public void remove() 
			{	 
				currentNode = beforeNode;
				if (null!=currentNode)
					{
					currentNode.setNext(null);
					size--;
					}
				else
				{
					_head = null;
				}
			}
		
		 };
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.stack.interfaces.ILifo#isEmpty()
	 */
	@Override
	public boolean isEmpty() {
		if (null == _head) return true;
		return false;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.stack.interfaces.ILifo#peek()
	 */
	@Override
	public V peek(){ //throws StackEmptyException {
	
		if (!isEmpty())
		{
			return _head.getValue();
		}
		return null;
		//throw new StackEmptyException();
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.stack.interfaces.ILifo#pop()
	 */
	@Override
	public V pop() {//throws StackEmptyException {
		
		if (!isEmpty())
		{
			V v = _head.getValue();
			_head= _head.getNext();
			size--;
			return v;
		}
		return null;
		//throw new StackEmptyException();
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.stack.interfaces.ILifo#push(java.lang.Object)
	 */
	@Override
	public void push(V arg0) {
	
		if (_head != null)
		{
			ILinkSimple<V> l = new LinkSimple<V>(arg0);
			l.setNext(_head);
			size++;
			_head = l;
			return;
		}

		_head = new LinkSimple<V>(arg0);
		size++;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.stack.interfaces.ILifo#size()
	 */
	@Override
	public int size() 
	{
		if (this.isEmpty()) return 0;
		//int i = 1;
		//Iterator<V> it = this.iterator();
		//while (null!=it.next()) {i++;}
		return size;
	}

}
